Skip to content

feat(scripts): custom-domain DNS automation and shared selectors#94

Merged
jamie-at-bunny merged 11 commits into
mainfrom
feat/scripts-custom-domains-dns
Jun 15, 2026
Merged

feat(scripts): custom-domain DNS automation and shared selectors#94
jamie-at-bunny merged 11 commits into
mainfrom
feat/scripts-custom-domains-dns

Conversation

@jamie-at-bunny

Copy link
Copy Markdown
Member

No description provided.

@bogdan-at-bunny

Copy link
Copy Markdown

@codex review

@changeset-bot

changeset-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cf857bc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@bunny.net/cli Minor
@bunny.net/cli-linux-x64 Minor
@bunny.net/cli-linux-arm64 Minor
@bunny.net/cli-darwin-x64 Minor
@bunny.net/cli-darwin-arm64 Minor
@bunny.net/cli-windows-x64 Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces custom-domain DNS automation for Edge Scripts: when a hostname lives in a Bunny DNS zone the CLI now detects it, offers to add/repoint a PULLZONE record, and then waits for propagation and issues SSL automatically — all in one guided flow. It also refactors script-selector boilerplate into shared selectScript/scriptSelectorBuilder helpers (used across show, stats, env *, deployments *) and adds dns zones link/unlink commands.

  • New core/hostnames/ modules (bunny-dns.ts, dns.ts, flow.ts): longest-suffix zone detection, injectable DNS resolvers with public-resolver fallback, and the offerBunnyDnsThenSsl / offerDnsWaitAndSsl orchestration that correctly isolates the zone-detection try/catch from user-confirmed writes.
  • scripts create / scripts init: gain a --domain flag and an interactive custom-domain prompt backed by the new setupCustomDomain helper; SSL issuance failures are warnings, not hard errors, since the script is already created.
  • Script command selector refactor: resolveManifestId + manual positional boilerplate replaced by selectScript / scriptSelectorBuilder / scriptIdOptionBuilder; commands now fall back to an interactive picker when no manifest or explicit ID is given, and always call offerLink after output.

Confidence Score: 4/5

Safe to merge after addressing the unsafe Id cast in the script picker's re-fetch path.

The new selectScript helper re-fetches the full script model after an interactive pick using selected.Id as number. Since EdgeScriptModel.Id is typed number | undefined, a script returned from the list endpoint without an ID would silently embed undefined in the fetch URL, producing a confusing 404. Every other path in this PR has solid guards for the same | undefined pattern (the existing.Id == null guard in bunny-dns.ts is the explicit fix for the equivalent issue raised last cycle).

packages/cli/src/commands/scripts/interactive.ts — the selected.Id as number cast on line 79 in the re-fetch added by this PR.

Important Files Changed

Filename Overview
packages/cli/src/core/hostnames/flow.ts New offerDnsWaitAndSsl + offerBunnyDnsThenSsl orchestration; correctly isolates the zone-detection try/catch from the record-offer and wait/SSL flow so user-confirmed errors surface cleanly.
packages/cli/src/core/hostnames/bunny-dns.ts New file: longest-suffix zone detection, add/repoint PULLZONE record with confirmation, and a guard for the existing.Id == null case that addresses the previously flagged issue.
packages/cli/src/core/hostnames/commands.ts Add handler now wires Bunny DNS detection (offerBunnyDnsThenSsl) ahead of manual CNAME instructions; --wait flag and targetPositional shared selector both added. Flow logic is sound.
packages/cli/src/commands/scripts/create.ts Adds --domain flag and shared setupCustomDomain helper; JSON mode handles domain failure gracefully and still reports the created script.
packages/cli/src/commands/scripts/interactive.ts Adds selectScript/scriptSelectorBuilder/scriptIdOptionBuilder shared selectors and re-fetches the full script model after picking from the list; the selected.Id as number cast before the re-fetch is unsafe (P1).
packages/cli/src/commands/dns/zone/link.ts New dns zones link command; zone.Id is typed `number
packages/cli/src/commands/dns/interactive.ts Adds manifest fallback before the zone picker, autoLinkDnsZone (silent write / prompted re-link), and offerLink in resolveZoneInteractive; also corrects the error hint from dns zone add to dns zones add.
packages/cli/src/commands/scripts/init.ts Custom-domain prompt wired in after script creation; failure is caught and warned rather than aborting the command, which is correct since the script already exists.

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as CLI (add / create)
    participant BunnyDNS as Bunny DNS API
    participant PullZone as Pull Zone API
    participant DnsPoll as DNS Poll (system + 1.1.1.1/8.8.8.8)

    User->>CLI: domains add shop.example.com [--wait]
    CLI->>PullZone: addHostname(shop.example.com)
    PullZone-->>CLI: hostnames + cnameTarget

    alt Interactive / TTY
        CLI->>BunnyDNS: findBunnyDnsZone(shop.example.com)
        BunnyDNS-->>CLI: "match { zoneId, delegated }"

        alt Zone found
            CLI->>User: Point shop.example.com at this pull zone?
            User-->>CLI: yes

            alt "delegated == true"
                CLI->>BunnyDNS: addPullZoneRecord / repointPullZoneRecord
                BunnyDNS-->>CLI: ok
                CLI->>PullZone: enableSsl (up to 3 attempts)
                PullZone-->>CLI: certificate issued
                CLI->>User: SSL certificate issued
            else "delegated == false"
                CLI->>BunnyDNS: addPullZoneRecord
                BunnyDNS-->>CLI: ok
                CLI->>User: Zone not delegated — update registrar NS
            end

        else Zone not found
            CLI->>User: CNAME shop.example.com to system-hostname
            CLI->>User: Wait for DNS and enable HTTPS now?
            User-->>CLI: yes / --wait
            loop Poll every 5s (max 10 min)
                CLI->>DnsPoll: anyResolverPointsAt?
                DnsPoll-->>CLI: true
            end
            CLI->>PullZone: enableSsl
            PullZone-->>CLI: certificate issued
            CLI->>User: SSL certificate issued
        end
    end
Loading

Fix All in Claude Code

Reviews (10): Last reviewed commit: "autolink dns and scripts" | Re-trigger Greptile

Comment thread packages/cli/src/core/hostnames/bunny-dns.ts
Comment thread packages/cli/src/core/hostnames/bunny-dns.ts
Comment thread packages/cli/src/core/hostnames/commands.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

if (args.output === "json") {
logger.log(
JSON.stringify(
{
hostname,
pullZoneId,
cnameTarget: systemHostname ?? null,
ssl: sslIssued,
forceSSL: sslIssued && force,
sslError: sslError ?? null,
},
null,
2,
),
);
// Emit the full result for agents/CI, then signal failure with a non-zero exit.
if (sslFailed) process.exit(1);
return;

P2 Badge Honor --wait before returning JSON

When scripts domains add is run in automation as --wait --output json, this branch returns immediately after adding the hostname, before the later offerDnsWaitAndSsl path can poll DNS and issue the certificate. The command therefore exits successfully with ssl: false even though the user explicitly requested the wait/SSL flow; handle --wait before the JSON return or emit JSON after the wait result is known.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/commands/scripts/init.ts Outdated
Comment thread packages/cli/src/commands/scripts/create.ts Outdated
@jamie-at-bunny

Copy link
Copy Markdown
Member Author

@greptile-apps re-review

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

Comment thread packages/cli/src/core/hostnames/commands.ts Outdated
Comment thread packages/cli/src/core/hostnames/flow.ts
Comment thread packages/cli/src/core/hostnames/flow.ts
@jamie-at-bunny jamie-at-bunny merged commit e2def53 into main Jun 15, 2026
2 checks passed
@jamie-at-bunny jamie-at-bunny deleted the feat/scripts-custom-domains-dns branch June 15, 2026 11:55
@github-actions github-actions Bot mentioned this pull request Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants